﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.IO;
using System.Windows.Forms;
using System.Data;

using AppDialogBox;

namespace PasswordControl
{
    static class Encryption
    {
        // Encrypt a string into a string using a password 
        //    Uses Encrypt(byte[], byte[], byte[]) 
        static public string Encrypt(string clearText, string Password)
        {
            // First we need to turn the input string into a byte array. 

            byte[] clearBytes = System.Text.Encoding.Unicode.GetBytes(clearText);

            // Then, we need to turn the password into Key and IV 

            // We are using salt to make it harder to guess our key

            // using a dictionary attack - 

            // trying to guess a password by enumerating all possible words. 

            PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });

            // Now get the key/IV and do the Encryptionion using the

            // function that accepts byte arrays. 

            // Using PasswordDeriveBytes object we are first getting

            // 32 bytes for the Key 

            // (the default Rijndael key length is 256bit = 32bytes)

            // and then 16 bytes for the IV. 

            // IV should always be the block size, which is by default

            // 16 bytes (128 bit) for Rijndael. 

            // If you are using DES/TripleDES/RC2 the block size is

            // 8 bytes and so should be the IV size. 

            // You can also read KeySize/BlockSize properties off

            // the algorithm to find out the sizes. 

            byte[] EncryptionedData = Encrypt(clearBytes, pdb.GetBytes(32), pdb.GetBytes(16));

            // Now we need to turn the resulting byte array into a string. 

            // A common mistake would be to use an Encoding class for that.

            //It does not work because not all byte values can be

            // represented by characters. 

            // We are going to be using Base64 encoding that is designed

            //exactly for what we are trying to do. 

            return Convert.ToBase64String(EncryptionedData);
        }


        // Encrypt a byte array into a byte array using a key and an IV 
        static public byte[] Encrypt(byte[] clearData, byte[] Key, byte[] IV)
        {
            // Create a MemoryStream to accept the Encryptioned bytes 

            MemoryStream ms = new MemoryStream();

            // Create a symmetric algorithm. 

            // We are going to use Rijndael because it is strong and

            // available on all platforms. 

            // You can use other algorithms, to do so substitute the

            // next line with something like 

            //      TripleDES alg = TripleDES.Create(); 

            Rijndael alg = Rijndael.Create();

            // Now set the key and the IV. 

            // We need the IV (Initialization Vector) because

            // the algorithm is operating in its default 

            // mode called CBC (Cipher Block Chaining).

            // The IV is XORed with the first block (8 byte) 

            // of the data before it is Encryptioned, and then each

            // Encryptioned block is XORed with the 

            // following block of plaintext.

            // This is done to make Encryptionion more secure. 


            // There is also a mode called ECB which does not need an IV,

            // but it is much less secure. 

            alg.Key = Key;
            alg.IV = IV;

            // Create a CryptoStream through which we are going to be

            // pumping our data. 

            // CryptoStreamMode.Write means that we are going to be

            // writing data to the stream and the output will be written

            // in the MemoryStream we have provided. 

            CryptoStream cs = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write);

            // Write the data and make it do the Encryptionion 

            cs.Write(clearData, 0, clearData.Length);

            // Close the crypto stream (or do FlushFinalBlock). 

            // This will tell it that we have done our Encryptionion and

            // there is no more data coming in, 

            // and it is now a good time to apply the padding and

            // finalize the Encryptionion process. 

            cs.Close();

            // Now get the Encryptioned data from the MemoryStream.

            // Some people make a mistake of using GetBuffer() here,

            // which is not the right way. 

            byte[] EncryptionedData = ms.ToArray();

            return EncryptionedData;
        }


        // Encrypt bytes into bytes using a password 
        //    Uses Encrypt(byte[], byte[], byte[]) 
        static public byte[] Encrypt(byte[] clearData, string Password)
        {
            // We need to turn the password into Key and IV. 

            // We are using salt to make it harder to guess our key

            // using a dictionary attack - 

            // trying to guess a password by enumerating all possible words. 

            PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });

            // Now get the key/IV and do the Encryptionion using the function

            // that accepts byte arrays. 

            // Using PasswordDeriveBytes object we are first getting

            // 32 bytes for the Key 

            // (the default Rijndael key length is 256bit = 32bytes)

            // and then 16 bytes for the IV. 

            // IV should always be the block size, which is by default

            // 16 bytes (128 bit) for Rijndael. 

            // If you are using DES/TripleDES/RC2 the block size is 8

            // bytes and so should be the IV size. 

            // You can also read KeySize/BlockSize properties off the

            // algorithm to find out the sizes. 

            return Encrypt(clearData, pdb.GetBytes(32), pdb.GetBytes(16));
        }


        // Decrypt a byte array into a byte array using a key and an IV 
        static public byte[] Decrypt(byte[] cipherData, byte[] Key, byte[] IV)
        {
            try
            {
                // Create a MemoryStream that is going to accept the

                // Encryptioned bytes 

                MemoryStream ms = new MemoryStream();

                // Create a symmetric algorithm. 

                // We are going to use Rijndael because it is strong and

                // available on all platforms. 

                // You can use other algorithms, to do so substitute the next

                // line with something like 

                //     TripleDES alg = TripleDES.Create(); 

                Rijndael alg = Rijndael.Create();

                // Now set the key and the IV. 

                // We need the IV (Initialization Vector) because the algorithm

                // is operating in its default 

                // mode called CBC (Cipher Block Chaining). The IV is XORed with

                // the first block (8 byte) 

                // of the data after it is Encryptioned, and then each Encryptioned

                // block is XORed with the previous 

                // cipher block. This is done to make Encryptionion more secure. 

                // There is also a mode called ECB which does not need an IV,

                // but it is much less secure. 

                alg.Key = Key;
                alg.IV = IV;

                // Create a CryptoStream through which we are going to be

                // pumping our data. 

                // CryptoStreamMode.Write means that we are going to be

                // writing data to the stream 

                // and the output will be written in the MemoryStream

                // we have provided. 

                CryptoStream cs = new CryptoStream(ms, alg.CreateDecryptor(), CryptoStreamMode.Write);

                // Write the data and make it do the Encryptionion 

                cs.Write(cipherData, 0, cipherData.Length);

                // Close the crypto stream (or do FlushFinalBlock). 

                // This will tell it that we have done our Encryptionion

                // and there is no more data coming in, 

                // and it is now a good time to remove the padding

                // and finalize the Encryptionion process. 

                cs.Close();

                // Now get the Encryptioned data from the MemoryStream. 

                // Some people make a mistake of using GetBuffer() here,

                // which is not the right way. 

                byte[] EncryptionedData = ms.ToArray();

                return EncryptionedData;
            }
            catch 
            {
                AppDialogWrapper.PromptBox("Wrong password , Encryptionion of the data file has failed", "Login Failed");
                return null;
            }
        }


        // Decrypt a string into a string using a password 
        //    Uses Decrypt(byte[], byte[], byte[]) 
        static public string Decrypt(string cipherText, string Password)
        {
            // First we need to turn the input string into a byte array. 

            // We presume that Base64 encoding was used 

                // here's a very special note!!! I had a lot of exceptions here. 
                // the 64 base string is suppose to end with padding: '='. 
                // anything after the '=', needs to be removed
           //     cipherText = cipherText.Remove(cipherText.LastIndexOf("=")+1);

            byte[] cipherBytes = Convert.FromBase64String(cipherText);

            // Then, we need to turn the password into Key and IV 

            // We are using salt to make it harder to guess our key

            // using a dictionary attack - 

            // trying to guess a password by enumerating all possible words. 

            PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });

            // Now get the key/IV and do the Encryptionion using

            // the function that accepts byte arrays. 

            // Using PasswordDeriveBytes object we are first

            // getting 32 bytes for the Key 

            // (the default Rijndael key length is 256bit = 32bytes)

            // and then 16 bytes for the IV. 

            // IV should always be the block size, which is by

            // default 16 bytes (128 bit) for Rijndael. 

            // If you are using DES/TripleDES/RC2 the block size is

            // 8 bytes and so should be the IV size. 

            // You can also read KeySize/BlockSize properties off

            // the algorithm to find out the sizes. 

            byte[] EncryptionedData = Decrypt(cipherBytes, pdb.GetBytes(32), pdb.GetBytes(16));

            // Now we need to turn the resulting byte array into a string. 

            // A common mistake would be to use an Encoding class for that.

            // It does not work 

            // because not all byte values can be represented by characters. 

            // We are going to be using Base64 encoding that is 

            // designed exactly for what we are trying to do. 

            if (EncryptionedData == null) return null;
            return System.Text.Encoding.Unicode.GetString(EncryptionedData);
        }


        // Decrypt bytes into bytes using a password 
        //    Uses Decrypt(byte[], byte[], byte[]) 
        static public byte[] Decrypt(byte[] cipherData, string Password)
        {
            // We need to turn the password into Key and IV. 

            // We are using salt to make it harder to guess our key

            // using a dictionary attack - 

            // trying to guess a password by enumerating all possible words. 

            PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });

            // Now get the key/IV and do the Decryption using the 

            //function that accepts byte arrays. 

            // Using PasswordDeriveBytes object we are first getting

            // 32 bytes for the Key 

            // (the default Rijndael key length is 256bit = 32bytes)

            // and then 16 bytes for the IV. 

            // IV should always be the block size, which is by default

            // 16 bytes (128 bit) for Rijndael. 

            // If you are using DES/TripleDES/RC2 the block size is

            // 8 bytes and so should be the IV size. 


            // You can also read KeySize/BlockSize properties off the

            // algorithm to find out the sizes. 

            return Decrypt(cipherData, pdb.GetBytes(32), pdb.GetBytes(16));
        }


    
    }
 }


        

